// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package time

import "errors"

// A Ticker holds a synchronous channel that delivers `ticks' of a clock
// at intervals.
type Ticker struct {
	C <-chan Time // The channel on which the ticks are delivered.
	s chan<- int
}

// NewTicker returns a new Ticker containing a channel that will send the
// time with a period specified by the duration argument.
// It adjusts the intervals or drops ticks to make up for slow receivers.
// The duration d must be greater than zero; if not, NewTicker will panic.
func NewTicker(d Duration) *Ticker {
	if d <= 0 {
		panic(errors.New("non-positive interval for NewTicker"))
	}
	// Give the channel a 1-element time buffer.
	// If the client falls behind while reading, we drop ticks
	// on the floor until the client catches up.
	c := make(chan Time, 1)
	s := make(chan int, 1)
	t := &Ticker{
		C: c,
		s: s,
	}
	
	// Start timer.
	go func() {
		F: for {
			Sleep(d)

			select {
			case <-s:
				break F
			default:
			}
	
			select {
			case c <- Now():
			default:
			}
		}
	}()
	return t
}

// Stop turns off a ticker.  After Stop, no more ticks will be sent.
func (t *Ticker) Stop() {
	select {
	case t.s <- 1:
	default:
	}
}

// Tick is a convenience wrapper for NewTicker providing access to the ticking
// channel only.  Useful for clients that have no need to shut down the ticker.
func Tick(d Duration) <-chan Time {
	if d <= 0 {
		return nil
	}
	
	c := make(chan Time, 1)
	
	// Start timer.
	go func() {
		for {
			Sleep(d)

			select {
			case c <- Now():
			default:
			}
		}
	}()
	
	return c
}
